
//      浅拷贝和深拷贝看的是代码的实现
//      创建对象的方式
//      1.new
//      2.clone()


//      创建个引用类型
class Money implements Cloneable{
    public double m = 12.4;

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
class Person implements Cloneable{
    public String name;
    public int age;//简单类型
    public Money money = new Money();

    public void eat(){
        System.out.println("eat()");
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        Person tmp = (Person)super.clone();
//        money要进行clone 需要加入接口Cloneable 并且重写Money clone方法(鼠标右键)
        tmp.money = (Money) tmp.money.clone();
        return tmp;

//        return super.clone();//和下面两行相似
//        Person tmp = (Person)super.clone();
//        return tmp;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
public class TestDemo {


    public static void main1(String[] args) throws CloneNotSupportedException {
        Person person1 = new Person();
        person1.name = "haha";
        person1.age = 18;
//    1.clone()返回类型为object所以需要强制类型转换
//    2.一个对象要克隆产生一个副本 那么这个引用所引用的对象(person)一定是可克隆的
//    在Person后面 implements Cloneable 接口
//    3.还是会报错 cloneable是一个空接口 有啥作用 空接口-》标志接口-》代表当前这个类是可以被克隆的
//    4.需要重写cloneable方法  鼠标右键-generate-Override-clone()object
//    5.最后需要处理异常 鼠标放在clone上 添加异常处理
        Person person2 = (Person)person1.clone();
        System.out.println(person2);
        System.out.println("====================");//深拷贝
        person2.age = 99;
        System.out.println(person1);
        System.out.println(person2);
    }

//      引用Money (浅拷贝)
    public static void main2(String[] args) throws CloneNotSupportedException{
        Person person1 = new Person();
        Person person2 = (Person)person1.clone();
//        设  在栈上创建空间[person1指向0x123]   在堆上创建空间(地址0x123)[name  age  money()指向0x222]   在堆上创建空间(地址为0x222)[m=12.4]
//        clone副本  在栈上创建空间[person2指向0x456]   在堆上创建空间(地址0x456)[name  age  money()指向0x222]   在堆上创建空间(地址为0x222)[m=12.4]
        System.out.println(person1.money.m);
        System.out.println(person2.money.m);
        System.out.println("=========浅拷贝=======");//浅拷贝
        person1.money.m = 123.12;
        System.out.println(person1.money.m);
        System.out.println(person2.money.m);
    }

//      让money指向不同的地址  实现深拷贝
//      1.需要重写Person 的 clone()方法
    public static void main(String[] args) throws CloneNotSupportedException {
        Person person1 = new Person();
        Person person2 = (Person)person1.clone();
        System.out.println(person1.money.m);
        System.out.println(person2.money.m);
        System.out.println("=========深拷贝=======");//深拷贝
        person1.money.m = 123.12;
        System.out.println(person1.money.m);
        System.out.println(person2.money.m);
    }

}
